package com.xyhy.core.utils;

import jakarta.servlet.http.HttpServletRequest;

import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class CommonUtil {
  /**
   * 地球半径，单位 km
   */
  private static final double EARTH_RADIUS = 6378.137;

  /**
   * 获取两个点之间距离，返回单位为 米
   */
  public static double getDistance(double lng1, double lat1, double lng2, double lat2) {
    // 纬度
    double radLat1 = Math.toRadians(lat1);
    double radLat2 = Math.toRadians(lat2);
    // 经度
    double radLng1 = Math.toRadians(lng1);
    double radLng2 = Math.toRadians(lng2);
    // 纬度之差
    double a = radLat1 - radLat2;
    // 经度之差
    double b = radLng1 - radLng2;
    // 计算两点距离的公式
    double s =
            2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
    // 弧长乘地球半径, 返回单位: 米
    s = s * EARTH_RADIUS * 1000;
    return s;
  }

  /**
   * 通过HttpServletRequest返回IP地址
   */
  public static String getIpAddr(HttpServletRequest request) {
    String ipAddress = request.getHeader("x-forwarded-for");
    if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
      ipAddress = request.getHeader("Proxy-Client-IP");
    }
    if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
      ipAddress = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
      ipAddress = request.getRemoteAddr();
      String localIp = "127.0.0.1";
      String localIpv6 = "0:0:0:0:0:0:0:1";
      if (ipAddress.equals(localIp) || ipAddress.equals(localIpv6)) {
        // 根据网卡取本机配置的IP
        InetAddress inet = null;
        try {
          inet = InetAddress.getLocalHost();
          ipAddress = inet.getHostAddress();
        } catch (UnknownHostException e) {
          e.printStackTrace();
        }
      }
    }
    // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
    String ipSeparate = ",";
    int ipLength = 15;
    if (ipAddress != null && ipAddress.length() > ipLength) {
      if (ipAddress.indexOf(ipSeparate) > 0) {
        ipAddress = ipAddress.substring(0, ipAddress.indexOf(ipSeparate));
      }
    }
    return ipAddress;
  }

  /**
   * 获取用户真实IP地址，不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
   * 参考文章： http://developer.51cto.com/art/201111/305181.htm
   * <p>
   * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值，究竟哪个才是真正的用户端的真实IP呢？
   * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
   * <p>
   * 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130,
   * 192.168.1.100
   * <p>
   * 用户真实IP为： 192.168.1.110
   *
   * @param request
   * @return
   */
  public static String getIpAddrTmp(HttpServletRequest request) {
    String ip = request.getHeader("x-forwarded-for");
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("HTTP_CLIENT_IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("HTTP_X_FORWARDED_FOR");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getRemoteAddr();
    }
    return ip;
  }

  /**
   * 获取资源目录下的文件流
   */
  public static InputStream getResourceStream(String resourcePath) {
    return Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath);
  }

  public static String paramLost(String param, String paramText) {
    String text = Optional.ofNullable(paramText).map(x -> String.format("(%s)", x)).orElse("");
    return String.format("参数缺失：%s%s", param, text);
  }

  public static String cannotFindById(Long id, String objText) {
    objText = Optional.ofNullable(objText).map(x -> String.format("“%s”", x)).orElse("“对象”");
    return String.format("无法通过id找到%s：%d", objText, id);
  }

  public static String cannotFindByParam(Object param, String paramText, String objText) {
    objText = Optional.ofNullable(objText).map(x -> String.format("“%s”", x)).orElse("“对象”");
    return String.format("无法通过%s找到%s：%s", paramText, objText, param.toString());
  }

  /**
   * 格式化字符串，删除换行，制表符等
   */
  public static String formatString(String str) {
    if (Objects.nonNull(str)) {
//			Pattern p = Pattern.compile("\\s*|\t|\r|\n");
      Pattern p = Pattern.compile("\t|\r|\n");
      Matcher m = p.matcher(str);
      return m.replaceAll("");
    }
    return str;
  }

}
